﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web;
using System.Web.UI;
using HtmlAgilityPack;
using System.Text.RegularExpressions;


namespace RelaxUI
{
    /// <summary>
    /// AJAX输出过滤器
    /// </summary>
    internal class ResponseFilter : Stream
    {
        #region fields

        private Stream _responseStream;
        private MemoryStream _memoryStream;

        #endregion

        #region Constructor

        internal ResponseFilter(Stream responseStream)
        {
            _responseStream = responseStream;
            _memoryStream = new MemoryStream();
        }

        #endregion

        #region overrides

        public override bool CanRead
        {
            get { return false; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            _memoryStream.Flush();
        }

        public override long Length
        {
            get { return 0; }
        }

        public override long Position
        {
            get { return 0; }
            set { }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return 0;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return 0;
        }

        public override void SetLength(long value)
        {
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _memoryStream.Write(buffer, offset, count);
        }

        public override void Close()
        {
            StringBuilder sb = new StringBuilder();
            ResolveResponseScripts(sb);

            string responseText = sb.ToString();

            // 文件上传，此时应该对返回的数据进行编码，因为ExtJs会将返回的数据放在<pre></pre>中，导致自定编码
            if (HttpContext.Current.Request.ContentType.Contains("multipart/form-data"))
            {
                // HttpUtility.UrlEncode 在 Encode 的时候, 将空格转换成加号，而客户端的 encodeURIComponent 则是将空格转换为 %20
                responseText = HttpUtility.UrlEncode(responseText);
                responseText = responseText.Replace("+", "%20");
            }

            // 从输出流创建TextWriter
            TextWriter writer = new StreamWriter(_responseStream, Encoding.UTF8);

            writer.Write(responseText);

            // 输出
            writer.Flush();
            writer.Dispose();
            base.Close();
            _responseStream.Close();
        }



        #endregion

        #region ResolveResponseScripts

        private void ResolveResponseScripts(StringBuilder sb)
        {
            // 我们不需要把Response的代码放在自执行的函数中，因为在X.ajax.js中，通过new Function(scripts)();来执行Response的代码。
            // Wrapper all the JavaScript in a self-execution function to prevent pollution of global JavaScript namespace.
            //writer.Write("(function(){");

            #region 网页重定向

            // 重定向页面
            if (HttpContext.Current.Response.RedirectLocation != null)
            {
                sb.Append("window.location.replace('" + HttpContext.Current.Response.RedirectLocation + "');");
                return;
            }

            #endregion

            #region 生成的HTML代码

            // 生成的页面内容
            string completeHtml = GetCompleteHtml();

            HtmlDocument doc = new HtmlDocument();
            doc.OptionFixNestedTags = true;
            doc.LoadHtml(completeHtml);

            #endregion
            
            
            //writer.Write("})();");

            #region oldcode
            //List<ScriptBlock> sortedList = ResourceManager.Instance.GetSortedControlScriptList();
            //for (int i = 0, count = sortedList.Count; i < count; i++)
            //{
            //    //Control control = sortedList[i].Control as Control;
            //    string scriptContent = sortedList[i].Script;

            //    // 如果要注册脚本为空，则跳过
            //    if (String.IsNullOrEmpty(scriptContent))
            //    {
            //        continue;
            //    }

            //    // 换行符去掉
            //    scriptContent = scriptContent.Replace("\r\n", "");
            //    writer.Write(scriptContent);
            //} 
            #endregion
        }

        #endregion

        #region GetCompleteHtml & GetHtmlNodeValue & GetHtmlNodeOuterHTML

        ///// <summary>
        ///// 取得 HTML 中一个节点的值
        ///// </summary>
        ///// <param name="searchValue"></param>
        ///// <param name="completeHtml"></param>
        ///// <returns></returns>
        //public string GetHtmlNodeValue(string searchValue, string completeHtml)
        //{
        //    //string search = "<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\"";
        //    int si = completeHtml.IndexOf(searchValue);
        //    if (si >= 0)
        //    {
        //        si += searchValue.Length;
        //        int ei = completeHtml.IndexOf('\"', si);
        //        if (ei >= 0)
        //        {
        //            return completeHtml.Substring(si, ei - si);
        //        }
        //    }

        //    return null;
        //}


        /// <summary>
        /// 取得 HTML 中一个节点的值
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public string GetHtmlNodeValue(string nodeId, HtmlDocument doc)
        {
            HtmlNode node = doc.DocumentNode.SelectSingleNode("//*[@id='" + nodeId + "']");
            if (node != null)
            {
                return node.Attributes["value"].Value;
            }
            return null;
        }

        /// <summary>
        /// 取得 HTML 中一个节点的OuterHtml
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public string GetHtmlNodeOuterHTML(string nodeId, HtmlDocument doc)
        {
            HtmlNode node = doc.DocumentNode.SelectSingleNode("//*[@id='" + nodeId + "']");
            if (node != null)
            {
                return node.OuterHtml;
            }
            return null;
        }

        public string GetHtmlNodeInnerHTML(string nodeId, HtmlDocument doc)
        {
            HtmlNode node = doc.DocumentNode.SelectSingleNode("//*[@id='" + nodeId + "']");
            if (node != null)
            {
                return node.InnerHtml;
            }
            return null;
        }

        /// <summary>
        /// 获取当前输出流的HTML内容
        /// </summary>
        /// <returns></returns>
        public string GetCompleteHtml()
        {
            string _completeHtml;

            _memoryStream.Position = 0;
            using (TextReader reader = new StreamReader(_memoryStream))
            {
                _completeHtml = reader.ReadToEnd();
            }

            return _completeHtml;
        }

        #endregion

    }
}
